#ifndef _UNION_ITEM_H
#define _UNION_ITEM_H

#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"

class UnionAward
{
public:
    struct AwardItem
    {
        int id;
        int num;
    };

    struct AwardWarplane
    {
        int id;
        int starLevel;
        int level;
    };

    struct AwardWingplane
    {
        int id;
        int starLevel;
        int level;
    };

    enum UNION_VIRTUAL_ITEM_TYPE
    {
        UNION_VIRTUAL_ITEM_NONE,
        UNION_VIRTUAL_ITEM_ITEM,
        UNION_VIRTUAL_ITEM_MONEY,
        UNION_VIRTUAL_ITEM_DIAMOND,
        UNION_VIRTUAL_ITEM_WARPLANE,
        UNION_VIRTUAL_ITEM_WINGPLANE,
    };

    UnionAward()
    {
        mType = UNION_VIRTUAL_ITEM_NONE;
    }

    UNION_VIRTUAL_ITEM_TYPE getType() const
    {
        return mType;
    }

    void    setItem(int id, int num)
    {
        mData.item.id = id;
        mData.item.num = num;
        mType = UNION_VIRTUAL_ITEM_ITEM;
    }

    bool    getItem(AwardItem& out) const
    {
        if (mType == UNION_VIRTUAL_ITEM_ITEM)
        {
            out = mData.item;
            return true;
        }

        return false;
    }

    void    setMoney(int value)
    {
        mData.money = value;
        mType = UNION_VIRTUAL_ITEM_MONEY;
    }

    bool    getMoney(int& money) const
    {
        if (mType == UNION_VIRTUAL_ITEM_MONEY)
        {
            money = mData.money;
            return true;
        }

        return false;
    }

    void    setDiamond(int value)
    {
        mData.diamond = value;
        mType = UNION_VIRTUAL_ITEM_DIAMOND;
    }

    bool    getDiamond(int& diamond) const
    {
        if (mType == UNION_VIRTUAL_ITEM_DIAMOND)
        {
            diamond = mData.diamond;
            return true;
        }

        return false;
    }

    void    setWarplane(int id, int starLevel, int level)
    {
        mData.warplane.id = id;
        mData.warplane.starLevel = starLevel;
        mData.warplane.level = level;
        mType = UNION_VIRTUAL_ITEM_WARPLANE;
    }

    bool    getWarplane(AwardWarplane& out) const
    {
        if (mType == UNION_VIRTUAL_ITEM_WARPLANE)
        {
            out = mData.warplane;
            return true;
        }

        return false;
    }

    void    setWingplane(int id, int starLevel, int level)
    {
        mData.wingplane.id = id;
        mData.wingplane.starLevel = starLevel;
        mData.wingplane.level = level;
        mType = UNION_VIRTUAL_ITEM_WINGPLANE;
    }

    bool    getWingplane(AwardWingplane& out) const
    {
        if (mType == UNION_VIRTUAL_ITEM_WINGPLANE)
        {
            out = mData.wingplane;
            return true;
        }

        return false;
    }

    void                unpackFromJson(const rapidjson::Value& json)
    {
        mType = (UNION_VIRTUAL_ITEM_TYPE)json.FindMember("type")->value.GetInt();
        if (mType == UNION_VIRTUAL_ITEM_MONEY)
        {
            mData.money = json.FindMember("money")->value.GetInt();
        }
        else if (mType == UNION_VIRTUAL_ITEM_DIAMOND)
        {
            mData.diamond = json.FindMember("diamond")->value.GetInt();
        }
        else if (mType == UNION_VIRTUAL_ITEM_ITEM)
        {
            mData.item.id = json.FindMember("id")->value.GetInt();
            mData.item.num = json.FindMember("num")->value.GetInt();
        }
        else if (mType == UNION_VIRTUAL_ITEM_WARPLANE)
        {
            mData.warplane.id = json.FindMember("id")->value.GetInt();
            mData.warplane.starLevel = json.FindMember("starLevel")->value.GetInt();
            mData.warplane.level = json.FindMember("level")->value.GetInt();
        }
        else if (mType == UNION_VIRTUAL_ITEM_WINGPLANE)
        {
            mData.wingplane.id = json.FindMember("id")->value.GetInt();
            mData.wingplane.starLevel = json.FindMember("starLevel")->value.GetInt();
            mData.wingplane.level = json.FindMember("level")->value.GetInt();
        }
        else
        {
            assert(false);
        }
    }

    rapidjson::Value    packToJson(rapidjson::Document& doc)
    {
        rapidjson::Value msg(rapidjson::kObjectType);

        msg.AddMember("type", mType, doc.GetAllocator());

        if (mType == UNION_VIRTUAL_ITEM_MONEY)
        {
            msg.AddMember("money", mData.money, doc.GetAllocator());
        }
        else if (mType == UNION_VIRTUAL_ITEM_DIAMOND)
        {
            msg.AddMember("diamond", mData.diamond, doc.GetAllocator());
        }
        else if (mType == UNION_VIRTUAL_ITEM_ITEM)
        {
            msg.AddMember("id", mData.item.id, doc.GetAllocator());
            msg.AddMember("num", mData.item.num, doc.GetAllocator());
        }
        else if (mType == UNION_VIRTUAL_ITEM_WARPLANE)
        {
            msg.AddMember("id", mData.warplane.id, doc.GetAllocator());
            msg.AddMember("starLevel", mData.warplane.starLevel, doc.GetAllocator());
            msg.AddMember("level", mData.warplane.level, doc.GetAllocator());
        }
        else if (mType == UNION_VIRTUAL_ITEM_WINGPLANE)
        {
            msg.AddMember("id", mData.warplane.id, doc.GetAllocator());
            msg.AddMember("starLevel", mData.warplane.starLevel, doc.GetAllocator());
            msg.AddMember("level", mData.warplane.level, doc.GetAllocator());
        }
        else
        {
            assert(false);
        }

        return msg;
    }

private:

    UNION_VIRTUAL_ITEM_TYPE mType;
    union
    {
        AwardItem item;
        int money;
        int diamond;
        AwardWarplane warplane;
        AwardWingplane wingplane;
    }mData;
};

#endif